package com.ssy.lingxi.member.merchant.serviceimpl.web;

import com.ssy.lingxi.common.constant.basic.EnableDisableStatus;
import com.ssy.lingxi.common.constant.order.OrderTypeEnum;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.member.merchant.api.constant.TradeCommentHistoryStatusEnum;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberTradeCommentSubmitDetailVO;
import com.ssy.lingxi.member.merchant.config.ServiceConfig;
import com.ssy.lingxi.member.merchant.entity.MemberOrderCommentDO;
import com.ssy.lingxi.member.merchant.entity.MemberOrderProductCommentDO;
import com.ssy.lingxi.member.merchant.entity.MemberTradeCommentHistoryDO;
import com.ssy.lingxi.member.merchant.api.constant.MemberRelationTypeEnum;
import com.ssy.lingxi.member.merchant.model.constant.MemberTradeTypeEnum;
import com.ssy.lingxi.member.merchant.repository.MemberOrderCommentRepository;
import com.ssy.lingxi.member.merchant.repository.MemberOrderProductCommentRepository;
import com.ssy.lingxi.member.merchant.repository.MemberRelationRepository;
import com.ssy.lingxi.member.merchant.repository.MemberTradeCommentHistoryRepository;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberCreditAsyncService;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberLevelAsyncService;
import com.ssy.lingxi.member.merchant.service.feign.IPlatformManageFeignService;
import com.ssy.lingxi.member.merchant.service.feign.IReportFeignService;
import com.ssy.lingxi.order.api.feign.OrderFeignService;
import com.ssy.lingxi.order.api.model.vo.request.OrderCommentFeignVO;
import com.ssy.lingxi.platform.manage.api.model.vo.parameter.PlatformParameterManageVO;
import com.ssy.lingxi.report.api.enums.OperateDataSourceEnum;
import com.ssy.lingxi.report.api.enums.PurchaseOrderOperateTypeEnum;
import com.ssy.lingxi.report.api.enums.SaleOrderOperateTypeEnum;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 会员评论服务接口基础实现类
 * @author yzc
 * @version 2.0.0
 * @date 2021/9/3
 */
@Service
public class BaseMemberCommentServiceImpl {

    private static final Logger log = LoggerFactory.getLogger(BaseMemberCommentServiceImpl.class);

    @Resource
    private MemberTradeCommentHistoryRepository memberTradeCommentHistoryRepository;

    @Resource
    private MemberRelationRepository relationRepository;

    @Resource
    private IPlatformManageFeignService platformManageFeignService;

    @Resource
    private IBaseMemberLevelAsyncService memberLevelAsyncService;

    @Resource
    private IBaseMemberCreditAsyncService memberCreditAsyncService;

    @Resource
    private IReportFeignService reportFeignService;

    @Resource
    private MemberOrderCommentRepository memberOrderCommentRepository;

    @Resource
    private MemberOrderProductCommentRepository memberOrderProductCommentRepository;

    @Resource
    private OrderFeignService orderFeignService;

    /**
     *
     * @param memberTradeTypeEnum 评价类型
     * @param memberOrderCommentDO 待评价订单
     * @param commentSubmitDetailList 提交的评价数据
     * @param isSensitiveWord 是否要过滤敏感词 0-否 1-是
     * @return 返回结果
     */
    protected Wrapper<Void> baseSubmitMemberTradeComment(MemberTradeTypeEnum memberTradeTypeEnum, MemberOrderCommentDO memberOrderCommentDO, List<MemberTradeCommentSubmitDetailVO> commentSubmitDetailList, boolean isSensitiveWord) {
        // 订单商品
        List<MemberOrderProductCommentDO> memberOrderProductCommentDOList = memberOrderProductCommentRepository.findAllByOrderId(memberOrderCommentDO.getId());
        if (CollectionUtils.isEmpty(memberOrderProductCommentDOList)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        // 检验所有订单商品评价状态
        if (checkOrderCommentComplete(memberTradeTypeEnum, memberOrderProductCommentDOList)) {
            return Wrapper.success();
        }

        // 已评价的订单商品记录
        List<MemberTradeCommentHistoryDO> memberTradeCommentHistoryDOList = memberTradeCommentHistoryRepository.findAllByOrderIdAndTradeType(memberOrderCommentDO.getId(), memberTradeTypeEnum.getTypeEnum());

        // 未评价的订单商品 orderProductId - orderProduct
        Map<Long, MemberOrderProductCommentDO> orderProductMap = memberOrderProductCommentDOList.stream()
                .filter(orderProduct -> memberTradeCommentHistoryDOList.stream().noneMatch(comm -> orderProduct.getId().equals(comm.getOrderProductId())))
                .collect(Collectors.toMap(MemberOrderProductCommentDO::getId, e -> e, (e1, e2) -> e2));

        // 可用的提交的评价数据(尚未评价的且start非空)
        List<MemberTradeCommentSubmitDetailVO> usableSubmitCommentDetailList = commentSubmitDetailList.stream()
                .filter(commentSubmit -> orderProductMap.containsKey(commentSubmit.getOrderProductId()) && Objects.nonNull(commentSubmit.getStar()))
                .collect(Collectors.toList());

        // 无可用提交的数据则返回
        if (CollectionUtils.isEmpty(usableSubmitCommentDetailList)) {
            return Wrapper.success();
        }

        // 获取敏感词
        List<String> submitComment = usableSubmitCommentDetailList.stream().map(MemberTradeCommentSubmitDetailVO::getComment).collect(Collectors.toList());
        if (isSensitiveWord) {
            // 需要过滤敏感词
            Wrapper<List<String>> filterResult = platformManageFeignService.filterSensitiveWordList(submitComment);
            if (filterResult.getCode() != ResponseCode.SUCCESS.getCode()) {
                return Wrapper.fail(filterResult.getCode(), filterResult.getMessage());
            }

            submitComment = filterResult.getData();
        }

        // 保存评价记录
        saveTradeComment(memberTradeTypeEnum, memberOrderCommentDO, usableSubmitCommentDetailList, submitComment, orderProductMap);

        // 检查订单商品是否评价完
        handleOrderCommentComplete(memberTradeTypeEnum, memberOrderCommentDO);

        return Wrapper.success();
    }

    /**
     * 检查订单是否已评价完
     * @param memberTradeTypeEnum 评价类型
     * @param memberOrderProductCommentDOList 待评价的订单商品
     * @return true, false
     */
    private boolean checkOrderCommentComplete(MemberTradeTypeEnum memberTradeTypeEnum, List<MemberOrderProductCommentDO> memberOrderProductCommentDOList) {
        // 判断是否所有订单商品都评价
        if (MemberTradeTypeEnum.BUYER.equals(memberTradeTypeEnum)) {
            // 采购会员
            return memberOrderProductCommentDOList.stream().map(e -> EnableDisableStatus.ENABLE.getCode().equals(e.getBuyerCommentStatus())).reduce((e1, e2) -> e1 && e2).orElse(false);
        } else {
            // 供应会员
            return memberOrderProductCommentDOList.stream().map(e -> EnableDisableStatus.ENABLE.getCode().equals(e.getVendorCommentStatus())).reduce((e1, e2) -> e1 && e2).orElse(false);
        }
    }

    /**
     * 检查订单商品是否评价完, 并处理完成后的逻辑
     * @param memberTradeTypeEnum 评价类型
     * @param memberOrderCommentDO 待评价订单
     */
    private void handleOrderCommentComplete(MemberTradeTypeEnum memberTradeTypeEnum, MemberOrderCommentDO memberOrderCommentDO) {
        // 注意jpa的缓存陷阱, 详情可以了解jpa session 的一级, 二级缓存, 如果同一个事务中多次调用同一个sql, 那么就会命中session的缓存,返回的旧数据
        // 解决方法为,更新语句执行后需要清除entityManager的缓存
        // 重新查询一遍订单商品数据
        List<MemberOrderProductCommentDO> updateOrderProductComment = memberOrderProductCommentRepository.findAllByOrderId(memberOrderCommentDO.getId());

        if (MemberTradeTypeEnum.BUYER.equals(memberTradeTypeEnum)) {
            Boolean allCommonStatus = updateOrderProductComment.stream().map(orderProduct -> EnableDisableStatus.ENABLE.getCode().equals(orderProduct.getBuyerCommentStatus())).reduce((e1, e2) -> e1 && e2).orElse(false);
            if (allCommonStatus) {
                // 更新订单评价状态
                memberOrderCommentRepository.updateBuyerCompleteCommentStatus(EnableDisableStatus.ENABLE.getCode(), memberOrderCommentDO.getId());

                // 调用会员计算权益相关
                executeMemberCalRight(memberTradeTypeEnum, memberOrderCommentDO);

                // 首页统计
                reportFeignService.executeReduceReport(OperateDataSourceEnum.TRADE_PURCHASE_ORDER.getCode(), PurchaseOrderOperateTypeEnum.TO_BE_EVALUATE.getCode(),
                        memberOrderCommentDO.getBuyerMemberId(), memberOrderCommentDO.getBuyerRoleId());

                // 通知订单服务修改状态
                OrderCommentFeignVO orderCommentFeignVO = new OrderCommentFeignVO();
                orderCommentFeignVO.setOrderId(memberOrderCommentDO.getId());
                orderCommentFeignVO.setBuyerCommentComplete(true);
                orderCommentFeignVO.setVendorCommentComplete(false);
                orderFeignService.updateOrderComment(orderCommentFeignVO);
            }
        } else {
            Boolean allCommonStatus = updateOrderProductComment.stream().map(orderProduct -> EnableDisableStatus.ENABLE.getCode().equals(orderProduct.getVendorCommentStatus())).reduce((e1, e2) -> e1 && e2).orElse(false);
            if (allCommonStatus) {
                // 更新订单评价状态
                memberOrderCommentRepository.updateVendorCompleteCommentStatus(EnableDisableStatus.ENABLE.getCode(), memberOrderCommentDO.getId());

                // 调用会员计算权益相关
                executeMemberCalRight(memberTradeTypeEnum, memberOrderCommentDO);

                // 首页统计
                reportFeignService.executeReduceReport(OperateDataSourceEnum.TRADE_SALE_ORDER.getCode(), SaleOrderOperateTypeEnum.TO_BE_EVALUATE.getCode(),
                        memberOrderCommentDO.getVendorMemberId(), memberOrderCommentDO.getVendorRoleId());

                // 通知订单服务修改状态
                OrderCommentFeignVO orderCommentFeignVO = new OrderCommentFeignVO();
                orderCommentFeignVO.setOrderId(memberOrderCommentDO.getId());
                orderCommentFeignVO.setBuyerCommentComplete(false);
                orderCommentFeignVO.setVendorCommentComplete(true);
                orderFeignService.updateOrderComment(orderCommentFeignVO);
            }
        }

    }

    /**
     * 保存评价记录并更新订单商品的评价状态
     * @param memberTradeTypeEnum 评价类型
     * @param memberOrderCommentDO 待评价订单
     * @param usableSubmitCommentDetailList 可评价的商品
     * @param submitComment 评论内容
     * @param orderProductMap 订单商品
     */
    private void saveTradeComment(MemberTradeTypeEnum memberTradeTypeEnum, MemberOrderCommentDO memberOrderCommentDO, List<MemberTradeCommentSubmitDetailVO> usableSubmitCommentDetailList, List<String> submitComment, Map<Long, MemberOrderProductCommentDO> orderProductMap) {
        // 保存的评价数据
        List<MemberTradeCommentHistoryDO> saveCommentHistoryDOList = new ArrayList<>();
        // 需要更新的订单商品
        List<Long> updateOrderProductList = new ArrayList<>();

        Integer commentShow = TradeCommentHistoryStatusEnum.SHOW.getCode();
        Wrapper<PlatformParameterManageVO> parameterManageVOWrapper = platformManageFeignService.parameterManageDetails(ServiceConfig.ORDER_COMMENT_SHOW_PARAMETER_CODE);
        if (ResponseCode.SUCCESS.getCode() == parameterManageVOWrapper.getCode()) {
            PlatformParameterManageVO data = parameterManageVOWrapper.getData();
            if (EnableDisableStatus.ENABLE.getCode().equals(data.getState()) && Objects.nonNull(data.getParameterValue())) {
                int value = data.getParameterValue().intValue();
                if (Stream.of(EnableDisableStatus.values()).anyMatch(e -> e.getCode().equals(value))) {
                    commentShow = EnableDisableStatus.ENABLE.getCode().equals(value) ? 1 : 2;
                } else {
                    log.error("订单评价显示设置参数有误, paramCode: {}, paramValue: {}", data.getCode(), data.getParameterValue());
                }
            }
        }

        for (int i = 0; i < usableSubmitCommentDetailList.size(); i++) {
            MemberTradeCommentSubmitDetailVO submitDetailVO = usableSubmitCommentDetailList.get(i);
            MemberOrderProductCommentDO memberOrderProductCommentDO = orderProductMap.get(submitDetailVO.getOrderProductId());
            if (Objects.isNull(memberOrderProductCommentDO)) {
                continue;
            }

            // 保存的评价记录
            submitDetailVO.setComment(CollectionUtils.isEmpty(submitComment) ? submitDetailVO.getComment() : submitComment.get(i));
            MemberTradeCommentHistoryDO commentHistoryDO = this.buildMemberTradeCommentHistoryDO(memberTradeTypeEnum, memberOrderCommentDO, memberOrderProductCommentDO, submitDetailVO, commentShow);
            saveCommentHistoryDOList.add(commentHistoryDO);

            // 更新的订单商品
            updateOrderProductList.add(submitDetailVO.getOrderProductId());
        }

        // 无可保存的数据则返回
        if (CollectionUtils.isEmpty(saveCommentHistoryDOList)) {
            return;
        }

        // 保存评价记录
        memberTradeCommentHistoryRepository.saveAll(saveCommentHistoryDOList);
        // 后续更新操作,涉及把jpa上下文的缓存清空,所以先持久化
        memberTradeCommentHistoryRepository.flush();

        // 更新订单商品评价状态
        if (CollectionUtils.isNotEmpty(updateOrderProductList)) {
            if (MemberTradeTypeEnum.BUYER.equals(memberTradeTypeEnum)) {
                // 执行更新, 并且清除该实体的session缓存
                memberOrderProductCommentRepository.updateBuyerCommentStatus(EnableDisableStatus.ENABLE.getCode(), updateOrderProductList);
            } else {
                // 执行更新, 并且清除该实体的session缓存
                memberOrderProductCommentRepository.updateVendorCommentStatus(EnableDisableStatus.ENABLE.getCode(), updateOrderProductList);
            }
        }
    }

    /**
     * 调用会员内部接口计算会员相关权益
     * @param memberTradeTypeEnum 评价类型
     * @param memberOrderCommentDO 被评价的订单
     */
    private void executeMemberCalRight(MemberTradeTypeEnum memberTradeTypeEnum, MemberOrderCommentDO memberOrderCommentDO) {
        Long memberId;
        Long roleId;
        String memberName;
        Long subMemberId;
        Long subRoleId;
        String subMemberName;
        if (MemberTradeTypeEnum.BUYER.equals(memberTradeTypeEnum)) {
            // 评论方
            memberId = memberOrderCommentDO.getBuyerMemberId();
            roleId = memberOrderCommentDO.getBuyerRoleId();
            memberName = memberOrderCommentDO.getBuyerMemberName();
            // 被评论方
            subMemberId = memberOrderCommentDO.getVendorMemberId();
            subRoleId = memberOrderCommentDO.getVendorRoleId();
            subMemberName = memberOrderCommentDO.getVendorMemberName();
        } else {
            // 评论方
            memberId = memberOrderCommentDO.getVendorMemberId();
            roleId = memberOrderCommentDO.getVendorRoleId();
            memberName = memberOrderCommentDO.getVendorMemberName();
            // 被评论方
            subMemberId = memberOrderCommentDO.getBuyerMemberId();
            subRoleId = memberOrderCommentDO.getBuyerRoleId();
            subMemberName = memberOrderCommentDO.getBuyerMemberName();
        }

        // 非积分订单才计算
        if (!OrderTypeEnum.CREDITS_EXCHANGE.getCode().equals(memberOrderCommentDO.getOrderType())
                && !OrderTypeEnum.CHANNEL_POINT_EXCHANGE.getCode().equals(memberOrderCommentDO.getOrderType())) {
            //计算等级和信用等积分
            memberLevelAsyncService.calculateSubMemberCommentScore(subMemberId, subRoleId, memberId, roleId, memberOrderCommentDO.getOrderNo());

            // 查询订单完成评价后的评价记录
            List<MemberTradeCommentHistoryDO> calculateCommentHistoryDOList = memberTradeCommentHistoryRepository.findAllByOrderIdAndTradeType(memberOrderCommentDO.getId(), memberTradeTypeEnum.getTypeEnum());

            //平均评论星级
            int avgStar = calculateCommentHistoryDOList.stream().collect(Collectors.averagingInt(MemberTradeCommentHistoryDO::getStar)).intValue();
            memberCreditAsyncService.calculateMemberTradeCommentCredit(memberId, roleId, subMemberId, subRoleId, avgStar);
        }
    }

    /**
     * 构造MemberTradeCommentHistoryDO
     * @param memberTradeTypeEnum 评价类型
     * @param memberOrderCommentDO 待评价订单
     * @param memberOrderProductCommentDO 待评价商品
     * @param submitDetailVO 订单的评价
     * @param commentShow 是否显示评价 0-否 1-是
     * @return 返回结果
     */
    private MemberTradeCommentHistoryDO buildMemberTradeCommentHistoryDO(MemberTradeTypeEnum memberTradeTypeEnum, MemberOrderCommentDO memberOrderCommentDO, MemberOrderProductCommentDO memberOrderProductCommentDO, MemberTradeCommentSubmitDetailVO submitDetailVO, Integer commentShow) {
        Long memberId;
        Long roleId;
        String memberName;
        Long subMemberId;
        Long subRoleId;
        String subMemberName;
        if (MemberTradeTypeEnum.BUYER.equals(memberTradeTypeEnum)) {
            // 评论方
            memberId = memberOrderCommentDO.getBuyerMemberId();
            roleId = memberOrderCommentDO.getBuyerRoleId();
            memberName = memberOrderCommentDO.getBuyerMemberName();
            // 被评论方
            subMemberId = memberOrderCommentDO.getVendorMemberId();
            subRoleId = memberOrderCommentDO.getVendorRoleId();
            subMemberName = memberOrderCommentDO.getVendorMemberName();
        } else {
            // 评论方
            memberId = memberOrderCommentDO.getVendorMemberId();
            roleId = memberOrderCommentDO.getVendorRoleId();
            memberName = memberOrderCommentDO.getVendorMemberName();
            // 被评论方
            subMemberId = memberOrderCommentDO.getBuyerMemberId();
            subRoleId = memberOrderCommentDO.getBuyerRoleId();
            subMemberName = memberOrderCommentDO.getBuyerMemberName();
        }

        MemberTradeCommentHistoryDO commentHistoryDO = new MemberTradeCommentHistoryDO();
        commentHistoryDO.setCreateTime(LocalDateTime.now());
        commentHistoryDO.setRelType(MemberRelationTypeEnum.OTHER.getCode());
        commentHistoryDO.setMemberId(memberId);
        commentHistoryDO.setRoleId(roleId);
        commentHistoryDO.setMemberName(memberName);
        commentHistoryDO.setSubMemberId(subMemberId);
        commentHistoryDO.setSubRoleId(subRoleId);
        commentHistoryDO.setSubMemberName(subMemberName);
        commentHistoryDO.setStar(submitDetailVO.getStar());
        // 评价内容
        commentHistoryDO.setComment(submitDetailVO.getComment());
        commentHistoryDO.setStatus(commentShow);
        commentHistoryDO.setTradeType(memberTradeTypeEnum.getTypeEnum());
        commentHistoryDO.setOrderId(memberOrderCommentDO.getId());
        commentHistoryDO.setOrderNo(memberOrderCommentDO.getOrderNo());
        commentHistoryDO.setOrderType(memberOrderCommentDO.getOrderType());
        commentHistoryDO.setOrderProductId(submitDetailVO.getOrderProductId());
        commentHistoryDO.setShopId(memberOrderCommentDO.getShopId());
        commentHistoryDO.setShopType(memberOrderCommentDO.getShopType());
        commentHistoryDO.setShopEnvironment(memberOrderCommentDO.getShopEnvironment());
        commentHistoryDO.setProduct(memberOrderProductCommentDO.getName());
        commentHistoryDO.setProductId(memberOrderProductCommentDO.getProductId());
        commentHistoryDO.setSkuId(memberOrderProductCommentDO.getSkuId());
        commentHistoryDO.setCategory(memberOrderProductCommentDO.getCategory());
        commentHistoryDO.setBrand(memberOrderProductCommentDO.getBrand());
        commentHistoryDO.setSpec(memberOrderProductCommentDO.getSpec());
        commentHistoryDO.setProductImgUrl(memberOrderProductCommentDO.getLogo());
        commentHistoryDO.setDealTime(memberOrderCommentDO.getCreateTime());
        commentHistoryDO.setDealCount(memberOrderProductCommentDO.getQuantity());
        commentHistoryDO.setUnit(memberOrderProductCommentDO.getUnit());
        commentHistoryDO.setPrice(memberOrderProductCommentDO.getPrice());
        commentHistoryDO.setTotalPrice(memberOrderProductCommentDO.getAmount());
        commentHistoryDO.setPics(submitDetailVO.getPics());
        commentHistoryDO.setReplyStatus(EnableDisableStatus.DISABLE.getCode());
        return commentHistoryDO;
    }

}
